package service

import (
	"batbat-backend/app/model"
	"batbat-backend/library/crypto/aes"
	"batbat-backend/library/crypto/rsa"
	"batbat-backend/library/redis"
	"batbat-backend/library/response"
	"context"
	"github.com/gogf/gf/errors/gerror"
	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/net/ghttp"
	"github.com/gogf/gf/util/gvalid"
	"github.com/google/uuid"
	"strings"
)

var Rsa = rsaService{}

type rsaService struct{}

// Create 创建公私钥对
func (rs *rsaService) Create(ctx context.Context) (*model.RsaApiCreateResp, error) {
	// 当发生错误的时候返回的信息
	gerr := gerror.New("创建公私钥对失败")
	// 创建公私钥对
	keypair, err := rsa.NewKeypair()
	if err != nil {
		g.Log().Ctx(ctx).Errorf("创建公私钥对失败: %v", err)
		return nil, gerr
	}
	// 生成公私钥对的唯一id
	id := strings.ReplaceAll(uuid.NewString(), "-", "")
	// 将公钥使用aes加密
	pk, err := aes.Encrypt([]byte(keypair.PublicKey))
	if err != nil {
		g.Log().Ctx(ctx).Errorf("aes加密失败: %v", err)
		return nil, gerr
	}
	// 将私钥存入redis
	err = redis.Rsa.Set(ctx, id, keypair.PrivateKey)
	if err != nil {
		g.Log().Ctx(ctx).Errorf("存储私钥失败: %v", err)
		return nil, gerr
	}
	// 返回结果
	return &model.RsaApiCreateResp{
		Id:  id,
		Rsa: pk,
	}, nil
}

// Decrypt 解密数据
func (rs *rsaService) Decrypt(r *ghttp.Request, pointer interface{}) error {
	// 获取请求体
	var req *model.RsaServiceDecryptReq
	err := r.Parse(&req)
	if err != nil {
		response.Error(r, err)
	}
	// 获取私钥
	key, err := redis.Rsa.Get(r.Context(), req.Id)
	if err != nil {
		g.Log().Ctx(r.Context()).Errorf("获取私钥失败: %v", err)
		response.Error(r, gerror.New("发生错误, 请重试"))
	}
	// 解密数据
	err = rsa.DecryptEverything(req.Data, key, pointer)
	if err != nil {
		g.Log().Ctx(r.Context()).Errorf("解密失败: %v", err)
		return gerror.New("发生错误, 请稍后重试")
	}
	// 校验数据
	return gvalid.CheckStruct(r.Context(), pointer, nil)
}
